"""基础区块链适配器

定义区块链适配器的抽象接口和基础实现
"""

from abc import ABC, abstractmethod
from typing import Dict, List, Any, Optional, Union
from datetime import datetime
import asyncio
from utils.logger import get_logger
from utils.exceptions import AdapterException, ChainException
from middleware.unified_abstraction import (
    AccountInfo, BlockInfo, TransactionInfo, ContractInfo, ChainInfo
)

logger = get_logger(__name__)

class IBlockchainAdapter(ABC):
    """区块链适配器接口"""
    
    @abstractmethod
    def __init__(self, config: Dict[str, Any]):
        """初始化适配器"""
        pass
    
    # 连接管理
    @abstractmethod
    async def connect(self) -> bool:
        """连接到区块链网络"""
        pass
    
    @abstractmethod
    async def disconnect(self) -> bool:
        """断开区块链网络连接"""
        pass
    
    @abstractmethod
    async def is_connected(self) -> bool:
        """检查连接状态"""
        pass
    
    @abstractmethod
    async def get_chain_info(self) -> ChainInfo:
        """获取链信息"""
        pass
    
    # 账户管理
    @abstractmethod
    async def create_account(self, **kwargs) -> AccountInfo:
        """创建账户"""
        pass
    
    @abstractmethod
    async def get_account_info(self, address: str) -> AccountInfo:
        """获取账户信息"""
        pass
    
    @abstractmethod
    async def get_balance(self, address: str, token_address: str = None) -> float:
        """获取账户余额"""
        pass
    
    # 交易管理
    @abstractmethod
    async def send_transaction(self, transaction: Dict[str, Any]) -> str:
        """发送交易"""
        pass
    
    @abstractmethod
    async def get_transaction(self, tx_hash: str) -> TransactionInfo:
        """获取交易信息"""
        pass
    
    @abstractmethod
    async def get_transaction_receipt(self, tx_hash: str) -> Dict[str, Any]:
        """获取交易回执"""
        pass
    
    @abstractmethod
    async def estimate_gas(self, transaction: Dict[str, Any]) -> int:
        """估算Gas费用"""
        pass
    
    # 区块管理
    @abstractmethod
    async def get_latest_block(self) -> BlockInfo:
        """获取最新区块"""
        pass
    
    @abstractmethod
    async def get_block_by_number(self, block_number: int) -> BlockInfo:
        """根据区块号获取区块"""
        pass
    
    @abstractmethod
    async def get_block_by_hash(self, block_hash: str) -> BlockInfo:
        """根据区块哈希获取区块"""
        pass
    
    # 智能合约管理
    @abstractmethod
    async def deploy_contract(self, contract_data: Dict[str, Any]) -> ContractInfo:
        """部署智能合约"""
        pass
    
    @abstractmethod
    async def call_contract(self, contract_address: str, method: str, 
                          params: List[Any] = None, **kwargs) -> Any:
        """调用智能合约方法"""
        pass
    
    @abstractmethod
    async def get_contract_info(self, contract_address: str) -> ContractInfo:
        """获取智能合约信息"""
        pass
    
    # 事件监听
    @abstractmethod
    async def subscribe_events(self, event_filter: Dict[str, Any], 
                             callback: callable) -> str:
        """订阅事件"""
        pass
    
    @abstractmethod
    async def unsubscribe_events(self, subscription_id: str) -> bool:
        """取消事件订阅"""
        pass
    
    @abstractmethod
    async def get_logs(self, filter_params: Dict[str, Any]) -> List[Dict[str, Any]]:
        """获取事件日志"""
        pass

class BaseBlockchainAdapter(IBlockchainAdapter):
    """基础区块链适配器实现"""
    
    def __init__(self, config: Dict[str, Any]):
        """初始化基础适配器"""
        self.config = config
        self.chain_id = config.get('chain_id', 'unknown')
        self.node_url = config.get('node_url', '')
        self.timeout = config.get('timeout', 30)
        self.retry_attempts = config.get('retry_attempts', 3)
        self.retry_delay = config.get('retry_delay', 1)
        
        self._connected = False
        self._client = None
        self._subscriptions = {}
        
        logger.info(f"Initialized {self.__class__.__name__} for chain: {self.chain_id}")
    
    # 连接管理方法 - 简化实现，子类根据需要重写
    async def connect(self) -> bool:
        """连接到区块链网络"""
        if self._connected:
            return True
        
        await self._establish_connection()
        self._connected = True
        logger.info(f"Successfully connected to {self.chain_id}")
        return True
    
    async def disconnect(self) -> bool:
        """断开区块链网络连接"""
        if not self._connected:
            return True
        
        # 清理订阅
        for subscription_id in list(self._subscriptions.keys()):
            await self.unsubscribe_events(subscription_id)
        
        await self._close_connection()
        self._connected = False
        self._client = None
        logger.info(f"Disconnected from {self.chain_id}")
        return True
    
    async def is_connected(self) -> bool:
        """检查连接状态"""
        return self._connected and await self._check_connection_health()
    
    async def get_chain_info(self) -> ChainInfo:
        """获取链信息"""
        await self._ensure_connected()
        
        try:
            # 子类需要实现具体的链信息获取逻辑
            return await self._get_chain_info_impl()
        except Exception as e:
            raise ChainException(f"Failed to get chain info: {str(e)}", self.chain_id)
    
    async def _ensure_connected(self):
        """确保已连接"""
        if not await self.is_connected():
            await self.connect()
    
    async def _retry_operation(self, operation, *args, **kwargs):
        """重试操作"""
        last_exception = None
        
        for attempt in range(self.retry_attempts + 1):
            try:
                return await operation(*args, **kwargs)
            except Exception as e:
                last_exception = e
                if attempt < self.retry_attempts:
                    logger.warning(f"Operation failed (attempt {attempt + 1}/{self.retry_attempts + 1}): {str(e)}")
                    await asyncio.sleep(self.retry_delay * (attempt + 1))
                else:
                    logger.error(f"Operation failed after {self.retry_attempts + 1} attempts: {str(e)}")
        
        raise last_exception
    
    def _validate_address(self, address: str) -> bool:
        """验证地址格式（子类可重写）"""
        return bool(address and isinstance(address, str))
    
    def _validate_transaction_hash(self, tx_hash: str) -> bool:
        """验证交易哈希格式（子类可重写）"""
        return bool(tx_hash and isinstance(tx_hash, str))
    
    def _validate_block_identifier(self, identifier: Union[int, str]) -> bool:
        """验证区块标识符（子类可重写）"""
        return isinstance(identifier, (int, str))
    
    # 数据格式化方法 - 子类根据需要实现
    # 移除通用格式化方法，各子类根据自己的数据结构实现
    
    # 子类需要实现的抽象方法
    async def _establish_connection(self):
        """建立连接（子类实现）"""
        raise NotImplementedError("Subclass must implement _establish_connection")
    
    async def _close_connection(self):
        """关闭连接（子类实现）"""
        raise NotImplementedError("Subclass must implement _close_connection")
    
    async def _check_connection_health(self) -> bool:
        """检查连接健康状态（子类实现）"""
        raise NotImplementedError("Subclass must implement _check_connection_health")
    
    async def _get_chain_info_impl(self) -> ChainInfo:
        """获取链信息实现（子类实现）"""
        raise NotImplementedError("Subclass must implement _get_chain_info_impl")
    
    # 以下方法由子类根据具体区块链实现
    # 账户管理、交易管理、区块管理、智能合约管理、事件监听等方法
    
    async def unsubscribe_events(self, subscription_id: str) -> bool:
        """取消事件订阅（基础实现）"""
        if subscription_id in self._subscriptions:
            del self._subscriptions[subscription_id]
            return True
        return False